﻿using System;
using System.Text;
using System.Collections.Generic;
namespace GX
{
    public class PoolManagerService : IPoolManager
    {
        readonly List<int> _typeHashCodeList = new List<int>(128);
        readonly Dictionary<int, ObjectPool> _poolMap = new Dictionary<int, ObjectPool>(128);
        readonly Dictionary<int, int> _capacityMap = new Dictionary<int, int>();
        int _defaultCapacity = 32;
        public int defaultCapacity { 
            get { return _defaultCapacity; }
            set
            {
                if (value > 0)
                    _defaultCapacity = value;
                else
                    _defaultCapacity = 32;
            }
        }
        public void SetCapacity(int typeHashCode, int capacity)
        {
            _capacityMap[typeHashCode] = capacity;
             int index;
             if (ListSearch.BinarySearch(_typeHashCodeList, typeHashCode, out index))
             {
                 ObjectPool pool = _poolMap[index];
                 pool.capacity = capacity;
             }
        }
        public bool Get(int typeHashCode, out object item)
        {
            int index;
            if (ListSearch.BinarySearch(_typeHashCodeList, typeHashCode, out index))
            {
                ObjectPool pool = _poolMap[_typeHashCodeList[index]];
                if(pool.Get(out item))
                    return true;
            }
            item = null;
            return false;
        }
        public object Get(Type type)
        {
            object item;
            Get(type.GetHashCode(), out item);
            return item;
        }
        public void Release(object item)
        {
            var typeHashCode = item.GetType().GetHashCode();

            ObjectPool pool=null;
            int index;
            if (!ListSearch.BinarySearch(_typeHashCodeList, typeHashCode, out index))
            {
                pool = ObjectPool.GetTemporary();

                int capacity;
                if (!_capacityMap.TryGetValue(typeHashCode, out capacity))
                    capacity = _defaultCapacity;
                pool.capacity = capacity;

                _typeHashCodeList.Insert(index, typeHashCode);
                _poolMap[typeHashCode] = pool;
            }
            else
                pool = _poolMap[_typeHashCodeList[index]];
            pool.Release(item);
        }
        public void GC()
        {
            int len = _typeHashCodeList.Count;
            for (int i = len-1; i >= 0; --i)
            {
                var typeHashCode = _typeHashCodeList[i];
                var pool = _poolMap[typeHashCode];
                pool.GC();
                if (pool.deactiveCount == 0)
                {
                    _typeHashCodeList.RemoveAt(i);
                    _poolMap.Remove(typeHashCode);
                    ObjectPool.ReleaseTemporary(pool);
                }
            }
        }
    }
}